const { src, dest, watch, series, parallel } = require('gulp')
const htmlMin = require('gulp-htmlmin') // 压缩html
const babel = require('gulp-babel') // es6转成es5
const terser = require('gulp-terser') // 压缩代码
const less = require('gulp-less'); // 处理less
const postcss = require('gulp-postcss') // postcss
const postcssPresetEnv = require('postcss-preset-env')
const pxtoviewport = require("postcss-px-to-viewport") // PX 转 Viewport
const inject = require('gulp-inject') // 把css 和js注入到html
const fileinclude = require('gulp-file-include') // 文件引入快捷方式 以及组件的引入方式
const browserSync = require('browser-sync') // 本地服务
const del = require('del') // 删除某一个文件夹
const autoprefixer = require('gulp-autoprefixer') // gulp-autoprefixer这是一款自动管理浏览器前缀的插件，它可以解析CSS文件并且添加浏览器前缀到CSS内容里。
// const imagemin = require('gulp-imagemin') // 压缩图片
// 处理html的任务
const htmlTask = () => {
  // /**/* 这个是匹配src下面的所有的html文件包括子元素的
  // /* 这个是匹配src下面的直接子元素 html文件 不包括components文件下面的html
  return src("./src/**/*.html", { base: "./src" })
    /* .pipe(htmlMin({ // 压缩html
      collapseWhitespace: true
    })) */
    .pipe(
      fileinclude({
        prefix: "@@", // 用法 @@webRoot
        basepath: "@file",
        indent: true
      })
    )
    .pipe(dest("./dist"))
}

// 处理js的任务
const jsTask = () => {
  return src("./src/js/**.js", { base: "./src" }) // base: "./src" 可以让输出的文件在js下面 和 dest("./dist/js")同理
    /* .pipe(babel({ presets: ["@babel/preset-env"] })) */ // 普通项目不要用这个否则会出现gezhongbug 用es6的项目可以使用
    /* .pipe(terser({ mangle: { toplevel: true } })) */
    .pipe(dest("./dist"))
}

// 处理css less任务
const lessTask = () => {
  return src("./src/css/*.less", { base: "./src" })
    .pipe(less())
    .pipe(postcss([postcssPresetEnv()]))
    .pipe(postcss([pxtoviewport({ // 当设计图小于等于750时候就会使用vw适配页面
      unitToConvert: 'px',
      viewportWidth: 750,
      unitPrecision: 3,
      viewportUnit: 'vw',
      })]))
    .pipe(autoprefixer({ // 处理css中 添加浏览器前缀的任务
      overrideBrowserslist: ['> 1%', 'last 2 versions', 'Firefox ESR'],
      cascade: false //  是否美化属性值
    }))
    .pipe(dest("./dist"))
}

// 处理css 任务
const cssTask = () => {
  return src("./src/css/*.css", { base: "./src" })
    .pipe(postcss([postcssPresetEnv()]))
    .pipe(postcss([pxtoviewport({ // 当设计图小于等于750时候就会使用vw适配页面
      unitToConvert: 'px',
      viewportWidth: 750,
      unitPrecision: 3,
      viewportUnit: 'vw',
    })]))
    .pipe(autoprefixer({ // 处理css中 添加浏览器前缀的任务
      overrideBrowserslist: ['> 1%', 'last 2 versions', 'Firefox ESR'],
      cascade: false //  是否美化属性值
    }))
    .pipe(dest("./dist"))
}

// 把css js 等注入到html中
const injectHtml = () => {
  return src("./dist/*.html")
    .pipe(inject(src(["./dist/js/*.js", "./dist/css/*.css"]), { relative: true }))
    .pipe(dest('./dist'))
}

// 处理img
const imgTask = () => {
  return src('./src/img/*.{png,jpg,gif,ico,svg}', { base: "./src" })
    .pipe(dest('./dist'))
}

// 处理font文件
const fontTask = () => {
  return src('./src/font/*.*', { base: "./src" })
    .pipe(dest('./dist'))
}

// 搭建本地服务器
const bs = browserSync.create()
const serve = () => {
  // /**/* 这个是匹配src下面的所有的html文件包括子元素的
  // /* 这个是匹配src下面的直接子元素 html文件 不包括components文件下面的html
  watch("./src/**/*.html", series(htmlTask, injectHtml))
  watch("./src/components/*.tpl", series(htmlTask))
  watch("./src/js/*.js", series(jsTask, injectHtml))
  watch("./src/css/*.less", series(jsTask, lessTask))
  watch("./src/css/*.css", series(jsTask, cssTask))
  watch("./src/img/*.{png,jpg,gif,ico}", series(imgTask))
  // watch(`**`).on('change', bs.reload) // 只要文件有改动就开始刷新页面 这个方法不可取 会很慢
  bs.init({
    port: 8080,
    open: true,
    // files: "./dist/*", // 只能坚挺到dist文件夹下面的变动
    files: "**",
    server: {
      baseDir: "./dist"
    }
  })
}
const clean = () => {
  return del(["dist"])
}

const buildTask = series(clean, parallel(htmlTask, imgTask, jsTask, lessTask, cssTask, fontTask), injectHtml);
const serveTask = series(buildTask, serve);
module.exports = {
  serveTask,
  buildTask
}